package plugins

import (
	"bytes"
	"context"
	"fmt"
	"gitee.com/wudicaidou/menciis-pocx"
	"gitee.com/wudicaidou/menciis-pocx/pocbase"
	"strings"
	"time"
)

const (
	pkt = "\x00" + // session
		"\x00\x00\xc0" + // legth
		"\xfeSMB@\x00" + // protocol
		"\x00\x00" +
		"\x00\x00" +
		"\x00\x00" +
		"\x00\x00" +
		"\x1f\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"$\x00" +
		"\x08\x00" +
		"\x01\x00" +
		"\x00\x00" +
		"\x7f\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"x\x00" +
		"\x00\x00" +
		"\x02\x00" +
		"\x00\x00" +
		"\x02\x02" +
		"\x10\x02" +
		"\x22\x02" +
		"$\x02" +
		"\x00\x03" +
		"\x02\x03" +
		"\x10\x03" +
		"\x11\x03" +
		"\x00\x00\x00\x00" +
		"\x01\x00" +
		"&\x00" +
		"\x00\x00\x00\x00" +
		"\x01\x00" +
		"\x20\x00" +
		"\x01\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00\x00\x00" +
		"\x00\x00" +
		"\x03\x00" +
		"\x0e\x00" +
		"\x00\x00\x00\x00" +
		"\x01\x00" + //CompressionAlgorithmCount
		"\x00\x00" +
		"\x01\x00\x00\x00" +
		"\x01\x00" + //LZNT1
		"\x00\x00" +
		"\x00\x00\x00\x00"
)

type cve20200796 struct {
	Id     string   `yaml:"id" #:"id 信息"`
	Name   string   `yaml:"name" #:"插件名称"`
	Tags   []string `yaml:"tags"`
	config *pocx.Config
}

func Newcve20200796() *cve20200796 {
	return &cve20200796{
		Id:   "CNNVD-202003-607",
		Name: "cve20200796",
		Tags: []string{"microsoft"},
	}
}

func (c27 *cve20200796) Init(ctx context.Context) error {
	config, err := pocx.ContextConfig(ctx)
	if err != nil {
		return err
	}

	c27.config = config
	return nil
}

func (c27 *cve20200796) Meta() *pocbase.MetaInfo {
	return &pocbase.MetaInfo{
		Plugin: &pocbase.PluginInfo{
			ID:   c27.Id,
			Name: c27.Name,
		},
	}
}
func (c27 *cve20200796) Match(ctx context.Context, in []pocbase.Fingerprint) bool {
	if len(in) == 0 || len(c27.Tags) == 0 {
		return true
	} else {
		if len(in) > 0 {
			for _, v := range in {
				for _, y := range c27.Tags {
					if strings.Contains(strings.ToLower(v.Product), strings.ToLower(y)) {
						return true
					}
				}
			}
		}
		return false
	}
}
func (c27 *cve20200796) Scan(ctx context.Context, in interface{}) (pocbase.SnapShot, pocbase.Event, error) {
	c27.config.Logger.Debug("start cve20200796 scan")
	var snapShot pocbase.SnapShot
	srv, isService := in.(*pocbase.ServiceAsset)
	if !isService {
		return snapShot, nil, fmt.Errorf("not service asset")
	}
	conn, err := c27.config.NetClient.Dial(ctx, srv)
	if err != nil {
		return snapShot, nil, err
	}
	defer func() {
		if conn != nil {
			conn.Close()
		}
	}()
	_, err = conn.Write([]byte(pkt))
	if err != nil {
		return snapShot, nil, err
	}
	buff := make([]byte, 1024)
	n, err := conn.Read(buff)
	if err != nil {
		return snapShot, nil, err
	}
	if bytes.Contains(buff[:n], []byte("Public")) == true {
		return snapShot, &pocbase.VulEvent{
			Timestamp: time.Now(),
			Plugin: &pocbase.PluginInfo{
				ID:   c27.Id,
				Name: c27.Name,
			},
			Details: &pocbase.VulDetail{},
			Target: &pocbase.TargetInfo{
				Host: srv.Host,
				Path: "",
				Port: srv.Port,
			},
		}, nil
	}
	return snapShot, nil, err
}

func (c27 *cve20200796) Close() {
	return
}

func (c27 *cve20200796) SetProxy(proxy string) {}
